import shelljs from 'shelljs';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from "node:url";
import {randomChars } from '../utils.js';
import cp from 'child_process';

const fp = fs.promises;

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

async function spawn(cmd, params) {
    console.log('[c2rust spwan]', cmd, params);

    return new Promise((res, rej) => {
        let child = null;
        try {
            child = cp.spawn(cmd, params);
        } catch (e) {
            console.error("[c2rust spawn]", e);
            rej(e);
            return;
        }

        const output = {
            stdout: '',
            stderr: ''
        };

        child.stdout.on('data', data => {
            output.stdout += data.toString();
        })
        child.stderr.on('data', data => {
            output.stderr += data.toString();
        })

        child.on('error', (e) => {
            console.error('[c2rust spawn error]', e);
        })

        let stdoutEnded = false, stderrEnded = false;
        function tryClosing() {
            if (stdoutEnded && stderrEnded) {
                if (output.stderr) {
                    rej(output.stderr);
                } else {
                    res(output.stdout);
                }
            }
        }

        child.stdout.on('end', function () { stdoutEnded = true; tryClosing(); });
        child.stderr.on('end', function () { stderrEnded = true; tryClosing(); });
    })
}


export default async function(code) {

    return new Promise(async (resolve, reject) => {
    
        const c_code_dir = path.join(__dirname, '../../c_code');
        const temp_dir = randomChars();

        const temp_code_dir = path.join(c_code_dir, temp_dir);

        try {
            shelljs.mkdir('-p', temp_code_dir);
            shelljs.cp(path.join(c_code_dir, './CMakeLists.txt'), temp_code_dir);

            await fp.writeFile(temp_code_dir + '/source.c', code);

            shelljs.mkdir(temp_code_dir + '/build');
            shelljs.cd(temp_code_dir + '/build');
            // shelljs.exec('cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..');

            await spawn('cmake', ['-DCMAKE_EXPORT_COMPILE_COMMANDS=1', '..']);

            shelljs.cd(temp_code_dir);
            // shelljs.exec('c2rust transpile ./build/compile_commands.json');

            await spawn('c2rust', ['transpile', './build/compile_commands.json']);

            const rust_code = (await fp.readFile(temp_code_dir + '/source.rs')).toString();

            shelljs.rm('-rf', temp_code_dir);

            // console.log("Rust generated" + ' - ' + rust_code);

            return resolve(rust_code);
        } catch(e) {
            shelljs.rm('-rf', temp_code_dir);
            reject(e)
        }
    }) 
}